import Axios, {AxiosRequestConfig} from 'axios';
import {interceptors} from './proxy';

interface IRequestConfigOptions {
    params?: any;
    headers?: any;
    timeout?: number;
    cancelToken?: (message?: any) => void;
    onUploadProgress?: (e) => void;
}

export interface IRequestOptions {
    url: string;
    params?: any;
    data?: any;
    headers?: any;
    timeout?: number;
    cancelToken?: (message?: any) => void;
    onUploadProgress?: (e) => void;
}

export default class ServiceBase {
    public axios;
    public serviceContext;
    public requestTimeout;

    constructor(serviceContext) {
        this.axios = Axios.create({
            baseURL: serviceContext.serviceEndpoint,
            timeout: serviceContext.requestTimeout,
            withCredentials:
                typeof serviceContext.withCredentials === 'undefined' ? true : serviceContext.withCredentials,
        });
        this.requestTimeout = serviceContext.requestTimeout;
        this.serviceContext = serviceContext.info;
        interceptors(this.axios, serviceContext.isResponseDetail);
    }

    getRequestConfigWithAuth = (options: IRequestConfigOptions): AxiosRequestConfig => {
        options.params = options.params || {};
        options.headers = options.headers || {};
        let userInfo = this.serviceContext();
        options.headers['Authorization'] = userInfo ? 'Bearer ' + (userInfo.access_token || userInfo.accessToken) : '';
        // AxiosRequestConfig
        let result: any = {
            params: options.params,
            headers: options.headers,
            timeout: options.timeout ? options.timeout * 1000 : this.requestTimeout,
            onUploadProgress: options.onUploadProgress,
        };
        if (options.cancelToken) {
            result.cancelToken = new Axios.CancelToken(options.cancelToken);
        }
        return result;
    };

    get(options: IRequestOptions) {
        // logger.log({
        //   log: 'get: ' + url,
        //   params: {...params},
        //   headers: {...headers}
        // })
        let config = this.getRequestConfigWithAuth(options);
        return this.axios.get(options.url, config);
    }

    getWithoutToken(options: IRequestOptions) {
        let config: AxiosRequestConfig = {
            params: options.params,
            headers: options.headers,
            timeout: options.timeout || this.requestTimeout,
        };
        if (options.cancelToken) {
            config.cancelToken = new Axios.CancelToken((c) => {
                options.cancelToken = c;
            });
        }
        return this.axios.get(options.url, config);
    }

    postWithoutToken(options: IRequestOptions) {
        let config: AxiosRequestConfig = {
            params: options.params,
            headers: options.headers,
            timeout: options.timeout || this.requestTimeout,
        };
        if (options.cancelToken) {
            config.cancelToken = new Axios.CancelToken((c) => {
                options.cancelToken = c;
            });
        }
        // let config = this.getRequestConfigWithAuth(params, headers);
        return this.axios.post(options.url, options.data, config);
    }

    putWithoutToken(options: IRequestOptions) {
        let config: AxiosRequestConfig = {
            params: options.params,
            headers: options.headers,
            timeout: options.timeout || this.requestTimeout,
        };
        if (options.cancelToken) {
            config.cancelToken = new Axios.CancelToken((c) => {
                options.cancelToken = c;
            });
        }
        return this.axios.put(options.url, options.data, config);
    }

    post(options: IRequestOptions) {
        // logger.log({
        //   log: 'post: ' + url,
        //   data: {...data},
        //   params: {...params},
        //   headers: {...headers}
        // })
        let config = this.getRequestConfigWithAuth(options);
        return this.axios.post(options.url, options.data, config);
    }

    put(options: IRequestOptions) {
        // logger.log({
        //   log: 'put: ' + url,
        //   data: {...data},
        //   params: {...params},
        //   headers: {...headers}
        // })
        let config = this.getRequestConfigWithAuth(options);
        return this.axios.put(options.url, options.data, config);
    }

    delete(options: IRequestOptions) {
        // logger.log({
        //   log: 'put: ' + url,
        //   params: {...params},
        //   headers: {...headers}
        // })
        let config = this.getRequestConfigWithAuth(options);
        config.data = options.data;
        return this.axios.delete(options.url, config);
    }

    patch(options: IRequestOptions) {
        // logger.log({
        //   log: 'patch: ' + url,
        //   data: {...data},
        //   params: {...params},
        //   headers: {...headers}
        // })
        let config = this.getRequestConfigWithAuth(options);
        return this.axios.patch(options.url, options.data, config);
    }
}
